﻿package hanoi {
	/**
	 * Información de historial de una movida.
	 */
	public class Move {
		/**
		 * Id para la primera torre.
		 */
		public static const FIRST_TOWER:uint = 1;
		/**
		 * Id para la segunda torre.
		 */
		public static const SECOND_TOWER:uint = 2;
		/**
		 * Id para la tercera torre.
		 */
		public static const THIRD_TOWER:uint = 3;
		
		/**
		 * Id de la torre de origen de la movida.
		 */
		private var _from:uint;
		/**
		 * Id de la torre de destino de la movida.
		 */
		private var _to:uint;
		/**
		 * Movida anterior.
		 */
		private var _prev:Move;
		/**
		 * Movida siguiente.
		 */
		private var _next:Move;
		
		/**
		 * Constructor.
		 * @param from Id de la torre de origen de la movida.
		 * @param to Id de la torre de destino de la movida.
		 */
		public function Move(from:uint, to:uint) {
			_from = from;
			_to = to;
		}
		
		/**
		 * Id de la torre de origen de la movida.
		 */
		public function get from():uint {
			return _from;
		}
		
		/**
		 * Id de la torre de destino de la movida.
		 */
		public function get to():uint {
			return _to;
		}
		
		/**
		 * Movida anterior.
		 */
		public function get prev():Move {
			return _prev;
		}
		
		/**
		 * Movida siguiente.
		 */
		public function get next():Move {
			return _next;
		}
		
		/**
		 * Vincula esta movida con la que le sigue.
		 * @param next La siguiente movida.
		 */
		internal function link(next:Move):void {
			this._next = next;
			next._prev = this;
		}
		
		/**
		 * Aplica esta movida a un juego.
		 * @param game El juego donde realizar la movida.
		 */
		public function applyTo(game:Hanoi):void {
			getTower(game, from).moveDiscTo(getTower(game, to));
		}
		
		/**
		 * Representación textual del objeto.
		 */
		public function toString():String {
			return "[Move " + from + " to " + to + "]";
		}
		
		/**
		 * Crea una movida para el evento indicado.
		 * @param event Evento de movida.
		 * @return Movida correspondiente.
		 */
		public static function forMoveEvent(event:HanoiEvent):Move {
			return new Move(getTowerId(event.game, event.from), getTowerId(event.game, event.to));
		}
		
		/**
		 * Identifica una torre según su id.
		 * @param game El juego al que pertenece la torre.
		 * @param tower El id de la torre.
		 * @return La torre.
		 */
		public static function getTower(game:Hanoi, id:uint):Tower {
			switch (id) {
				case FIRST_TOWER: return game.firstTower;
				case SECOND_TOWER: return game.secondTower;
				case THIRD_TOWER: return game.thirdTower;
				default: return null;
			}
		}
		
		/**
		 * Identifica el id de una torre.
		 * @param game El juego al que pertenece la torre.
		 * @param tower La torre.
		 * @return El id de dicha torre.
		 */
		public static function getTowerId(game:Hanoi, tower:Tower):uint {
			if (tower == game.firstTower) return FIRST_TOWER;
			if (tower == game.secondTower) return SECOND_TOWER;
			if (tower == game.thirdTower) return THIRD_TOWER;
			return 0;
		}
	}
}
